﻿// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
using System;
using Microsoft.Internal;
using System.Collections.Generic;

namespace System.ComponentModel.Composition.ReflectionModel
{
    // Represents a 'specialization' of an Export[<T[,TMetadataView]>] and 
    // ExportCollection[<T[,TMetadataView]>], for example, Export<IFoo, IFooMetadata>.
    internal class SpecializedExportType
    {
        private readonly Type _collectionExportType;
        private readonly Type _elementExportType;
        private readonly Type _metadataViewType;

        private SpecializedExportType(Type collectionExportType, Type elementExportType, Type metadataViewType)
        {
            Assumes.NotNull(elementExportType);

            _collectionExportType = collectionExportType;
            _elementExportType = elementExportType;
            _metadataViewType = metadataViewType ?? ExportServices.DefaultMetadataViewType;
        }

        public Type CollectionExportType
        {
            get { return _collectionExportType; }
        }

        public Type ElementExportType
        {
            get { return _elementExportType; }
        }

        public Type MetadataViewType
        {
            get { return _metadataViewType; }
        }

        public static SpecializedExportType MakeExportType(Type type)
        {
            return MakeCore(type, MakeExportTypeFrom); 
        }

        public static SpecializedExportType MakeExportCollectionType(Type elementType)
        {
            return MakeCore(elementType, MakeExportCollectionTypeFrom);
        }

        private static SpecializedExportType MakeCore(Type type, Func<Type, Type, SpecializedExportType> creator)
        {
            Assumes.NotNull(type);

            if (!ExportServices.IsKnownExportType(type))
            {
                return null;
            }

            if (!type.IsGenericType)
            {
                return creator((Type)null, (Type)null);
            }

            Type[] arguments = type.GetGenericArguments();
            Assumes.IsTrue(arguments.Length == 1 || arguments.Length == 2);

            if (arguments.Length == 1)
            {
                return creator(arguments[0], (Type)null);
            }

            return creator(arguments[0], arguments[1]);
        }

        private static SpecializedExportType MakeExportTypeFrom(Type exportedObjectType, Type metadataViewType)
        {
            return new SpecializedExportType((Type)null,
                                             ExportServices.MakeGenericExportType(exportedObjectType, metadataViewType),
                                             metadataViewType);
        }

        private static SpecializedExportType MakeExportCollectionTypeFrom(Type exportedObjectType, Type metadataViewType)
        {
            Type collectionExportType = ExportServices.MakeGenericExportCollectionType(exportedObjectType, metadataViewType);

            return new SpecializedExportType(collectionExportType,
                                             ExportServices.MakeGenericExportType(exportedObjectType, metadataViewType),
                                             metadataViewType);
        }



    }
}
